home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-08-13 | 95.8 KB | 2,788 lines |
-
-
-
-
- Chapter 4
-
-
-
- Internal Description
-
-
-
- 4.1 Source File Structure
-
-
- The source tree of AmiTCP/IP is dividedto few main parts:
-
-
- 1. Directory sys contains BSD Unix system header files, which are ported
- to the Amiga environment.
-
-
- 2. Directory net contains modules for the general networking services.
- They are independent of any particular protocol family.
-
-
- 3. Directory netinet contains the modules for the internet (inet)
- protocol family. IP, ICMP, TCP and UDP are internet protocols.
-
-
- 4. Directory kern contains modules, which provide the BSD kernel
- environment for the networking routines.
-
-
- 5. Directory api contains the BSD socket compatible shared library API
- code.
-
-
- The filesare briefly described in the following paragraphs. Note that
-
- some of the header files are actually located to the NETINCLUDE:1
- directory.
-
-
-
- 4.1.1 System Include Files
-
- General Headers
-
-
- sys/cdefs.h Definitions to harmonize various C language dialects.
-
- sys/param.h General machine independent parameter definitions.
-
- sys/time.h Definition of structure timeval.
-
- sys/types.h Common C type definitions and file descriptorset macros
- for select().
-
-
- BSD Socket API
- ________________________________
- 1See section 3.1.3 on page 30.
-
-
-
- 69
-
-
- 70 Section 4.1 AmiTCP/IP System Manual
-
-
-
- sys/errno.h Error code definitions for system functions.
-
- sys/ioctl.h Definitions for socket IO control.
-
- sys/socket.h Definitions related to sockets: types, address
- families, options and prototypes.
-
- sys/uio.h IO structure definition for sendmsg() and recvmsg()2.
-
-
- BSD Kernel Data Structures
-
-
- sys/domain.h Domain structure and global domain pointer declarations.
-
- sys/kernel.h Global kernel variable definitions (used throughoutthe
- kernel).
-
- sys/malloc.h Defines the bsd_malloc() and bsd_free() functions.
-
- sys/mbuf.h Mbuf structure definition and inline macros.
-
- sys/protosw.h Protocol switch structure definition with related
- definitions (options, actions, etc.).
-
- sys/queue.h General queue data structures.
-
- sys/socketvar.h Socket structure definition and related utility
- macros.
-
- sys/synch.h Declarations for tsleep and spl functions.
-
- sys/syslog.h Logging related definitions.
-
- sys/systm.h System wide definitions and prototypes.
-
-
-
- 4.1.2 Protocol Independent Network Routines
-
- Network Interface
-
-
- net/if.c General network interface routines.
-
- net/if.h Defines the interface for network adapter drivers.
-
- net/if_arp.h General protocol independent ARP structures.
-
- net/if_dl.h Defines the Link Level sockaddr structure.
-
- net/if_loop.c Loopback device routines.
-
- net/if_sana.c Interface module for the SANA-IInetwork adapter
- drivers.
-
- net/if_sana.h Defines the interface for the SANA-II network adapter
- drivers.
-
- net/if_types.h Interface type numbers. Obsolete.
-
- net/netisr.h and
-
- net/netisr.c Defines the network input queue scheduling routines.
-
- net/sana2arp.c ARP routines for Sana-II devices.
-
- net/sana2arp.h SANA-II private ARP headers.
-
- net/sana2copybuff.c Buffer management routines called from SANA-II
- ________device_driver.__________
-
- 2These functions are not implemented in this release of the AmiTCP/IP
-
-
- System Manual AmiTCP/IP Section 4.1 71
-
-
-
- net/sana2errno.h SANA-II error lists and printing header.
-
- net/sana2request.c Moduleto handle SANA-II IO Requests.
-
- net/sana2request.h Inlineroutines to manage different SANA-II IO
- requests.
-
- net/sana2tags.c Common customization parameters for the sana_softc
- network interface.
-
- net/sana2tags.h Defines the tags to customize sana_softc network
- interface.
-
- netlib:sana2perror.c Printing routines for SANA-II error messages.
-
-
- Routing
-
-
- net/radix.c Routines for searching, adding and removing data items in
- the radix binary tree.
-
- net/radix.h Defines the radix tree data structures.
-
- net/route.c General, protocol independent routing functions.
-
- net/route.h Defines data structures for routing entries,tables and
- statistics.
-
- net/rtsock.c The socket interface to the routing information.
-
-
- Raw Sockets
-
-
- net/raw_cb.c Routines to manage the rawprotocol control blocks.
-
- net/raw_cb.h The raw protocol control block definition.
-
- net/raw_usrreq.c The raw socket interface to the low level protocols
- and network adapters.
-
-
-
- 4.1.3 Internet Protocol Modules
-
- Inet Domain
-
-
- netinet/in.c Generic Internet addressing routines.
-
- netinet/in.h Protocol numbers, port conventions, inet address
- definitions.
-
- netinet/in_cksum.c Calculates checksum for internet protocol headers.
-
- netinet/in_pcb.c Generic internet protocol routines, binding,
- addressing.
-
- netinet/in_pcb.h Declares generic internet protocol control block.
-
- netinet/in_proto.c Defines internet protocol control blocks.
-
- netinet/in_systm.h Some network byte order type definitions.
-
- netinet/in_var.h Define an interface address structure for internet.
-
-
- IP, ICMP
-
-
- netinet/icmp_var.h ICMP statistics.
-
- netinet/ip.h IP packet header, packet options, timestamp.
-
-
- 72 Section 4.1 AmiTCP/IP System Manual
-
-
-
- netinet/ip_icmp.c Routines to generate, receive and reflect ICMP
- packets.
-
- netinet/ip_icmp.h ICMP packet structure.
-
- netinet/ip_input.c IP input, packet reassemble and packet forwarding.
-
- netinet/ip_output.c IP output, packet fragmenting.
-
- netinet/ip_var.h Define IP statistics, external IP packet header,
- reassemble queues structures.
-
- netinet/raw_ip.c Provide a raw interface to the IP protocol.
-
-
- TCP
-
-
- netinet/tcp.h Define the TCP packet structure.
-
- netinet/tcp_debug.c TCP debugging routines.
-
- netinet/tcp_debug.h Header for TCP debugging.
-
- netinet/tcp_fsm.h TCP Finite State Machine states.
-
- netinet/tcp_input.c TCP input routines.
-
- netinet/tcp_output.c TCP output routines.
-
- netinet/tcp_seq.h TCP sequence numbering.
-
- netinet/tcp_subr.c Various TCP subroutines for initializing,
- connection maintenance etc.
-
- netinet/tcp_timer.c TCP timeout routines.
-
- netinet/tcp_timer.h TCP timing constants.
-
- netinet/tcp_usrreq.c Process TCP user requests (send, timeout),
- attach, disconnect.
-
- netinet/tcp_var.h Define TCP control block and TCP statistics.
-
- netinet/tcpip.h Define the overlaid TCPIP packet header structure.
-
-
- UDP
-
-
- netinet/udp.h Define the UDP packet structure.
-
- netinet/udp_usrreq.c Routines to UDP output, input and notification.
-
- netinet/udp_var.h Define UDPIP packet overlay, UDP statistics.
-
-
-
- 4.1.4 BSDKernel Service Modules
-
- BSD Kernel Support
-
-
- kern/amiga_includes.h Include file which includes all amiga specific
- include files.
-
- kern/amiga_main.c Main module of the AmiTCP/IP.
-
- kern/amiga_subr.h Miscellaneous function definitions (usually short
- inline functions).
-
- kern/amiga_time.c Timer module for the timeout functions.
-
- kern/amiga_time.h Amiga timer.device related functions.
-
-
- System Manual AmiTCP/IP Section 4.1 73
-
-
-
- kern/kern_malloc.c Malloc & free related functions.
-
- kern/kern_synch.c tsleep and spl function definitions.
-
- kern/uipc_mbuf.c Mbuf functions.
-
-
- Socket Level Functions
-
-
- kern/uipc_domain.c Domain functions, especially pfslowtimo() and
- pffasttimo().
-
- kern/uipc_socket.c Higher level so-level functions (socreate(),
- sobind() etc.).
-
- kern/uipc_socket2.c Lower level so-level functions (soisconnecting(),
- soqremque(), sowakeup() etc.).
-
-
- NETTRACE Maintenance Process Support
-
-
- kern/amiga_config.c Configuration and ARexx command support routines.
-
- kern/amiga_config.h Defines the structure for configuration
- variables.
-
- kern/amiga_cstat.c Query support routines.
-
- kern/amiga_log.c Functions for initialization of log task and code
- for task itself.
-
- kern/amiga_log.h Header file for logging functions.
-
- kern/amiga_netdb.c Network database parsing and support functions.
-
- kern/amiga_netdb.h Declares the network database structures and
- types.
-
- kern/amiga_rexx.c Arexx-interface.
-
- kern/amiga_rexx.h Arexx-interface definitions.
-
- kern/config_var.awk Awk script to generate both code and
- documentation from the file kern/variables.src.
-
- kern/subr_prf.c Interfaces for (s)printf(), panic() and log()
-
- kern/variables.src Definition and documentation for configuration
- variables
-
-
-
- 4.1.5 BSDSocket API
-
- Shared Library Interface
-
-
- api/allocdatabuffer.c Client data buffer allocation functions.
-
- api/allocdatabuffer.h Client data buffer allocation definitions.
-
- api/amiga_api.c Contains API initialization and deinitialization
- functions and data. Opening and Closing of the AmiTCP/IP socket
- library bases.
-
- api/amiga_api.h Description of the SocketBase structure (forinternal
- AmiTCP/IP use only), and some inline functions relatedto the API
- functionality.
-
-
- 74 Section 4.1 AmiTCP/IP System Manual
-
-
-
- api/amiga_libcallentry.h Included in every module which defines
- AmiTCP/IP socket library calls.
-
- api/amiga_libtables.c Exec library base list and AmiTCP/IP socket
- library function tables for MakeLibrary().
-
- api/amiga_raf.h Compiler dependent macros for Register Argument
- Functions.
-
- api/apicalls.h Includes either api/apicalls_gnuc.h or
- api/apicalls_sasc.h.
-
- api/apicalls_gnuc.h Inline functions for internal API calls for GNUC.
-
- api/apicalls_sasc.h Inline functions for internal API calls for SASC.
-
- API Functions
-
- api/amiga_generic.c General Unix system calls related to file
- descriptors ported for AmiTCP/IP socket library. There are also
- some Amiga specific extensions to the BSD Unix system calls in
- this module.
-
- api/amiga_libcalls.c Inet library functions (link library in Unix
- system). These inet functions are provided as a part of the
- AmiTCP/IP socket library.
-
- api/amiga_syscalls.c Standard BSD style socket functions ported to
- the AmiTCP/IP socket library.
-
- api/gethostnamadr.c Functions that calls resolver in order to obtain
- host information from nameserver. Calls netdatabase functions if
- information can not be resolved.
-
- api/gethtbynamadr.h Prototypes for two functions in api/getxbyy.h.
-
- api/getxbyy.c Host (without nameserver), network, service ja protocol
- query functions (also a link library in unix system).
-
- api/hostbuf.h Structure definition for host queries and few minor
- netdb stuff.
-
- Resolver Functions
-
- api/arpa_nameser.h Information for nameserver query.
-
- api/res_comp.c Routines to translate domain names between
- conventional ascii and the compressed format used in queries.
-
- api/res_debug.c Functions that output debugging information3
-
- api/res_init.h Resolver initializer function. Very simple in
- AmiTCP/IP implementation.
-
- api/res_mkquery.c Function that forms a domain name query in buffer.
-
- api/res_query.c Functions to generate query sequence and append
- domains to incomplete hostnames.
-
- api/res_send.c Function to send and receive query to and from a
- nameserver, respectively.
-
- api/resolv.h Resolver datatypes, defines, variables and prototypes.
- ________________________________
- 3If RES_DEBUG defined at compile time
-
-
- System Manual AmiTCP/IP Section 4.2 75
-
-
-
- 4.1.6 Miscellaneous Files
-
-
- Makefiles
-
-
- GCCOPTS Compiler options forthe GCC.
-
- GNUmakefile Makefile used with GNU make in HP-UX workstations, where
- the source tree is maintained.
-
- SCOPTIONS Compiler options for the SAS/C 6.x
-
- Smakefile Makefile for SAS/C smake 6.x to compile the AmiTCP/IP.
-
-
- Revision Support
-
-
- bsdsocket.library_rev.rev Contains revision numberof the current
- version (number of the latest build). This file is updated with
-
- the BumpRev utility4.
-
- bsdsocket.library_rev.h Automaticallygenerated by BumpRev. Contains
- build date, version and revision strings.
-
-
- SAS/C 6.x GST Support
-
-
- all_includes.c C file for GST generation. Just includes the
- all_includes.h file.
-
- all_includes.h Includes all header files needed by theAmiTCP/IP,
- which are suitable for inclusion in a GST. Note that any headers
- with inline functions can not be included in a GST.
-
-
- Other Files
-
-
- conf/conf.h Static configuration information in form of preprocessor
- defines. Every C module must include this as the first include
- file.
-
- conf/rcs.h RCS header inclusion macro for GCC. InSAS/C this macro is
- defined in the SCOPTIONS file.
-
- protos/*/*.h Prototypes for functions in various modules.
-
-
-
- 4.2 AmiTCP/IP Initialization
-
-
- All more or less distinct modules of theAmiTCP/IP must be initialized
- before they can be used for the real work. Initialization is done in
- module kern/amiga_main.c, which definesfunctions init_all() and
- deinit_all(). The main() function calls the init_all()after it has done
- all needed local initializations. If init_all() failsthe deinit_all() is
- called to clean up.
-
- ________________________________
- 4The BumpRev is supplied by Commodore.
-
-
- 76 Section 4.2 AmiTCP/IP System Manual
-
-
-
- 4.2.1 init _all()
-
- This function calls the initialization routines of all modules which have
- such. This must be done carefully in the correct partial order.
- There arefew general heuristics which can be applied on initialization
- (with respect to the ordering requirements):
-
-
- 1. Initialize the modules for which the initialization cannot fail.
- This includes semaphore initializations and such.
-
- 2. Initialize the modules which are most likely to fail, e.g. large
- memory allocations, modules which require recent versions of some
- libraries etc.
-
- 3. Initialize modules left over by rules 1 and 2.
-
-
- Semaphoreinitializations are first, because later steps may use them
- to protect against race conditions.
- The initialization process of the AmiTCP/IP is fully reversible. If
- the initialization fails in any step thedeinit _all() function can be
- used to collect the garbage.
- init_all() does the initializations in following order, returning
- nonzero if all steps succeed. Numbers in the parenthesis are the section
- and page numbers for more information, respectively:
-
-
- 1. malloc_init() initializes the malloc_semaphore. This is first since
- later steps may want to use bsd_malloc() to allocatememory (5.2.2,
- 95).
-
- 2. spl_init() initializes the priority level subsystem,which is used
- throughout the code to protect critical sections (5.3.1, 96).
-
- 3. sleep_init() initializes the sleep_semaphore and the sleep queues
- (5.3.2, 97).
-
- 4. readconfig() reads in and parses the command line arguments and the
- configuration file. This is the first phase which is expected to
- fail. This is done at the beginning in order to allow other
- initialization functions to use the configuration information given.
- Note that since the logging subsystem is not initialized yet,
- readconfig() cannot log any errors encountered (4.11, 91).
-
- 5. log_init() initializes the logging subsystem. From now on other
- initialization functions can log needed error messages (4.8, 89).
-
- 6. mbinit() allocates memory to be used by the protocols. This is a
- candidate to fail if the memory is nearly exhausted (4.5, 79).
-
- 7. timer_init() initializes the timeout module. This requires version
- 36 or greater of the operating system. Returns the signal mask to
- wait for the timeout messages (5.1, 93).
-
- 8. api_init() initializes and creates the master socketbase structure
- (4.10.2, 91).
-
- 9. res_init() initializes resolver structure and semaphore.
-
-
- System Manual AmiTCP/IP Section 4.3 77
-
-
-
- 10. sana_init() initializes the SANA-II network interface module. This
- returns the signal mask to be used for waiting the network related
- messages (4.7, 84).
-
- 11. domaininit() initializes all configured protocols. This is left at
- the end of the initialization, since this requires the other parts of
- the system to be initialized.
-
- 12. readnetdb() initializes and reads in the network data base
- information from ENV:AmInet/netdb (4.12, 92).
-
- 13. api_show() makes the shared library interface visible on the Exec
- library list (4.10.2, 91).
-
-
-
- 4.2.2 deinit _all()
-
- deinit_all() is the reverse of init_all(); it deinitializes required
- modules in reverse order with respect tothe initialization.
- If the initialization process for a module does not allocate any
- resources, then there is no deinitialization function for that module.
- The deinitialization functions called are (in this order):
-
-
- 1. api_hide() removes the library from the Exec librarylist, so no-one
- can open the library any more (4.10.2, 91).
-
- 2. sana_deinit() deinitializes the network driver module (4.7, 84).
-
- 3. api_deinit() deinitializes the API (4.10.2, 91).
-
- 4. timer_deinit() deinitializes the timer module (5.1,93).
-
- 5. mbdeinit() frees all memory used by mbufs (4.5, 79).
-
- 6. log_deinit() deinitializes the logging subsystem (4.8, 89).
-
-
-
- 4.3 The Main Module
-
-
- The main() function is defined in the file kern/amiga_main.c. On startup
- it initializes all modules by calling init _all(). After a successful
- initialization it first starts the AmiTCP/IP timeouts by calling
- timer_send(). Then it enters the event loop.
- AmigaOS function Wait() returns when one of the signals specified in
- the signal mask given as argument is received. The mask currently
- specifies signals for SANA-II drivers, timeouts and the break signal.
- When some set of these signals is received the Wait() returns and its
- return value, which indicates the received signals, is checked. The
- functions sana_poll() and timer_poll() are each called in turn if their
- signal was received. They each return boolean tellingif they would like
- to be called again before waiting again. The loop in which these
- functions are called is terminated either when no one of the poll
- functions wants to continue or when thebreak signal is received.
- The pollfunctions do handle only one message at a time, so that any of
- them should not starve.
-
-
- 78 Section 4.4 AmiTCP/IP System Manual
-
-
-
- When thebreak signal is received the AmiTCP/IP terminates if no
- library bases opened by API users are open any more. On termination all
- reserved resources are freed by callingdeinit _all().
-
-
-
- 4.4 Protocol Entities
-
-
- One design goal was to keep the protocolentities intact. This is
- achieved through implementing all external dependencies of the protocol
- entities. Fortunately the protocol entities in BSD arehighly
- independent of other UNIX kernel services. For example, all dynamic
-
- memory management is done through the memory buffer5 abstraction, which
- means that we only had to provide the mbuf interface and the problem of
- memory management was solved.
- All protocol entities in a protocol family are defined in terms of a
- protocol switch structure. This structure is fully defined in the header
- file sys/protosw.h and [Leffler et al 1991b ]. The protocol switch
- structure is defined as follows:
-
-
- struct protosw -
- short pr_type; /* socket type used for */
- struct domain *pr_domain; /* domain protocol a member of */
- short pr_protocol; /* protocol number */
- short pr_flags; /* protocol flags */
- /* protocol-protocol hooks */
- void (*pr_input)(); /* input to protocol (from below) */
- int (*pr_output)(); /* output to protocol (from above)*/
- void (*pr_ctlinput)(); /* control input (from below) */
- int (*pr_ctloutput)(); /* control output (from above) */
- /* user-protocol hook */
- int (*pr_usrreq)(); /* user request hook */
- /* utility hooks */
- void (*pr_init)(); /* initialization hook */
- void (*pr_fasttimo)(); /* fast timeout (200ms) */
- void (*pr_slowtimo)(); /* slow timeout (500ms) */
- void (*pr_drain)(); /* flush any excess space possible */
- ";
-
-
- Note thatthe actual prototypes for the function pointers are omitted,
- see the file sys/protosw.h for full definition.
- When protocol is started the pr_init() is called first to allow the
- protocol to initialize all needed internal structures. Then the input
- process will call pr_fasttimo() and pr_slowtimo() entries periodically if
-
- defined6. The pr_drain() entry asks the protocol tofree all
- non-critical memory buffers in a low-memory situation.
- Protocolscall each other through the protocol--protocol interface. To
- pass a packet up in the hierarchy a protocol calls the pr_input()-entry
- of the protocol above it. pr_output()-entry is called when a protocol
- wishes to pass a packet down in the protocol hierarchy (towards network).
- ________________________________
- 5or mbuf for short
-
- 6Member function is defined when the value of its address is not NULL.
-
-
- System Manual AmiTCP/IP Section 4.5 79
-
-
-
- Protocolssend control information to each other through the
- pr_ctlinput() and pr_ctloutput() entries.
- All requests coming from the API are dispatched through the pr_usrreq()
- entry.
-
-
-
- 4.5 Memory Management
-
-
- As stated earlier, the memory managementof the protocol stack is done
- with memory buffers. An mbuf is a structure containinglittle amount of
- storage (usually 128 bytes). Some bytes of this storage are used for the
- header, but most of it is used to storeuser data. These small buffers
- are linked together to get storage for larger data.
- Mbufs arehighly efficient in a network protocol environment where it
- must be able to attach and strip protocol headers with minimum overhead
- and most importantly, without copying the data as doing so. When data is
- stored in an mbuf chain, attaching a header is achieved by simply linking
- the mbuf containing the header to the head of the chain. Removing a
- header is also done simply by removing the first mbuf or by incrementing
- the data pointer inside the mbuf.
- In general there are two types of mbufs. Ones with an packet header
- and ones without. An Mbuf with packet header is used as the first mbuf
- of every packet. This header contains extra information needed per
- packet. See the header file sys/mbuf.h for the mbuf header definition.
- Mbufs canbe chained in two dimensions. First they may be linked to
- form the storage for the whole message. Second these messages may be
- linked together so that the boundaries of messages are maintained. This
- second feature is mainly used by messageoriented protocols such as UDP.
- To gain efficiency an mbuf may have a reference to external memory page
- (a cluster), where a big message is copied instead of splitting it apart
- to many mbufs. The main advantage of this feature is avoidance of
- copying the data when sending it with TCP, since the clusters are shared
-
- between copies7.
-
-
-
- 4.5.1 Mbuf Functions
-
-
- Mbufs are accessed through set of functions which can be grouped as
- follows:
-
-
-
- Maintenance
-
-
- int mb_check_conf(void *dp, LONG newvalue)
-
- Check configurable variable whose address is dp. Return TRUE if the
- newvalue is acceptable value for that variable. See section 4.11 for
- information about the configuration.
-
-
- BOOL mbinit(void)
- ________________________________
- 7TCP must keep a copy of the sent data for possible retransmissions.
-
-
- 80 Section 4.5 AmiTCP/IP System Manual
-
-
-
- Initialize the whole mbuf-subsystem. Allocate a chunk of mbufs and
- clusters (using m_alloc() and m_clalloc). Must be called before any
- other mbuf-related function (except that mb_check_conf() can be
- called anytime).
-
-
- void mbdeinit(void)
-
- Free all resources used by mbuf subsystem. Must be called as the
- last mbuf-related function in the program.
-
-
- BOOL m_alloc(int howmany, int canwait)
-
- Allocate howmany mbufs and place them on the mbuf free list. If
- canwait is true the caller can wait if memory is not readily
- available.
-
-
- BOOL m_clalloc(int ncl, int canwait);
-
- Allocate ncl mbuf clusters and place them on the cluster free list.
-
-
- struct mbuf *m_retry(int i, int t)
-
- Ask protocols to free space when short of memory and re-attempt to
- allocate an mbuf.
-
-
- void m_reclaim(void)
-
- Ask protocols to free space when short of memory.
-
-
-
- Allocation and Deallocation
-
- struct mbuf *m_get(int canwait, int type)
-
- Allocate an mbuf of type type. If no mbufs are available we can wait
- for them if canwait is M_WAIT. Initialize mbuf to contain internal
- data.
-
-
- void MGET(struct mbuf *m, int canwait, int type)
-
- This is an macro form of above.
-
-
- struct mbuf *m_gethdr(int canwait, int type)
-
- Allocate an mbuf of type type. If no mbufs are available we can wait
- for them if canwait is M_WAIT. Initialize mbuf to contain a packet
- header and internal data.
-
-
- void MGETHDR(struct mbuf *m, int canwait, int type)
-
- This is a macro form of above.
-
-
- struct mbuf *m_getclr(int canwait, int type)
-
- Allocate an mbuf of type type. If no mbufs are available we can wait
- for them if canwait is M_WAIT. If allocation succeeds the data buffer
- is zeroed before returning.
-
-
- MCLALLOC(struct mcluster *p, int canwait)
-
- A macro to allocate an mbuf cluster. The result is placed in p.
-
-
- System Manual AmiTCP/IP Section 4.5 81
-
-
-
- MCLGET(struct mcluster *p, int canwait)
-
- A macro to add a cluster to a normal mbuf. M_EXT flag of the mbufis
- set on success.
-
- struct mbuf *m_free(struct mbuf *m)
-
- Free an mbuf. Next mbuf in the chain is returned, if any.
-
- void MFREE(struct mbuf *m, struct mbuf *n)
-
- This is an macro form of above. Successor mbuf is returned in n.
-
- MCLFREE(struct mcluster *p)
-
- A macro to free an mbuf cluster.
-
- void m_freem(struct mbuf *m)
-
- Free the whole chain of mbufs starting from m.
-
-
-
- Utility Functions
-
- struct mbuf *m_copym(struct mbuf *m, intoff0, int len, int canwait)
-
- Make a copy of an mbuf chain starting off0 bytes from the beginning
- of m, continuing for len bytes. If len is M_COPYALL, copy to endof
- mbuf.
-
- void m_copydata(struct mbuf *m, int off,int len, caddr_t cp)
-
- Copy data from an mbuf chain starting off bytes from the beginning,
- continuing for len bytes, into buffer cp.
-
- struct mbuf *m_prepend(struct mbuf *m, int len, int canwait)
-
- Prepend a chain of mbufs (m) with new mbuf with len bytes allocated
- from the first mbuf aligned on a long word boundary.
-
- void M_PREPEND(struct mbuf *m, int plen,int canwait)
-
- Macro version of above optimized for the most general cases.
-
- void M_COPY_PKTHDR(struct mbuf *to, struct mbuf *from)
-
- Macro for copying an mbuf packet header from from to to. from must
- have flag M_PKTHDR set, and to must be empty.
-
- void M_ALIGN(struct mbuf *m, int len)
-
- Macro to set the m data pointer of a newly--allocated mbuf (with
- m_get()/MGET()) to place an object of the size len at the end of the
- mbuf, long word aligned.
-
- void MH_ALIGN(struct mbuf *m, int len)
-
- As above, but for mbufs allocated with m_gethdr()/MGETHDR() or
- initialized by M_COPY_PKTHDR().
-
- int M_LEADINGSPACE(struct mbuf *m)
-
- Compute the amount of space available before the current start of
- data in an mbuf.
-
-
- 82 Section 4.6 AmiTCP/IP System Manual
-
-
-
- int M_TRAILINGSPACE(struct mbuf *m)
-
- Compute the amount of space available after the end of data in an
- mbuf.
-
-
- void MCHTYPE(struct mbuf *m, type t)
-
- Change mbuf to a new type.
-
-
- void m_cat(struct mbuf *m, struct mbuf *n)
-
- Concatenate mbuf chain n to m. Both chains must be of the same type.
-
-
- m_adj(struct mbuf *mp, int req_len)
-
- Trim req_len bytes from the head of the mbuf chain mp if req_len is
- positive, else trim -- req_len bytes from the tail of the mbuf chain.
-
-
- struct mbuf *m_pullup(struct mbuf *n, int len)
-
- Rearrange an mbuf chain so that len bytes from the beginning of the
- mbuf chain n are contiguous and in the data area of the mbuf so that
- the data can be used as a structure.
-
-
-
- Utility Macros
-
- type t mtod(struct mbuf *m, type t)
-
- Convert mbuf pointer to a pointer to the start of the data area of
- the mbuf casted to type t.
-
-
- struct mbuf *dtom(type *x)
-
- Convert data pointer within an mbuf to mbuf pointer.
-
-
-
- 4.6 Concurrency Control
-
-
- The protocol implementation in the BSD net/2 is driven by network and
- timer interrupts and user processes calling the system functions. As the
- whole protocol stack is moved inside normal AmigaOS process, some
- modifications are in place.
- The processor priority levels are the main concurrency control tool of
- the BSD kernel. The levels defined are SPL0 (user level), SPLSOFTCLOCK,
- SPLNET and SPLIMP (the most privileged level). Execution at a higher
- level disables the execution at all lower levels. InAmiTCP/IP the
- concurrency control is implemented either with semaphores (when
- debugging) or with prevention of the task switches (Forbid()/Permit()),
- see section 5.3.1 on page 96 for the implementation notes.
- The protocol input and timeouts are driven by a single process that
- manages the whole protocol stack. The process sends appropriate IO
- requests to the timer device and the SANA-II device drivers in question.
- Actions are then taken as response to the returned requests. Before any
- protocol routines are called the priority level is raised either to
- SPLSOFTCLOCK or SPLNET. After the function returns the priority level is
- lowered back to SPL0 and the request issent back to the device driver.
-
-
- System Manual AmiTCP/IP Section 4.7 83
-
-
-
- On the API side the concurrent execution of system calls is mostly
- prohibited, because in UNIX the system calls are atomic in the sense that
- there is never more than one system callin execution. In AmigaOS the
- shared library functions must be re-entrant so the protection must be
- provided by the library functions themselves.
- The priority at which the main process runs must be above the default
- value of 0 to provide enough time to process the networking protocols.
- On the other side there is no sense to drive the main process at greater
- priority than the SANA-II device drivers.
-
-
-
- 4.7 Network Device Drivers
-
-
- AmiTCP/IP uses standard SANA-II driversas its external network device
- drivers. A little glue is needed to attach a SANA-II driver into BSD
- net/2 code.
-
-
-
- Network Interface
-
- The BSD net/2 networking code provides aclean interface to the network
- device drivers. The network interface provides a consistent interface
- for all protocols that may be present inthe BSD Unix kernel. Each
- hardware device is associated with an unique network interface which may
- be used by one or more protocol families.
- The network interface is flexible enough to attach different SANA-II
- network device drivers into the AmiTCP/IP networking system. Common
- part of all network interfaces is described in [Leffler et al 1991b ]:
-
-
- struct ifnet -
- char *if_name; /* name, e.g. "en" or "lo" */
- short if_unit; /* sub-unit for lower level driver */
- short if_mtu; /* maximum transmission unit */
- short if_flags; /* up/down, broadcast, etc. */
- short if_timer; /* time 'til if_watchdog called */
- int if_metric; /* routing metric (external only) */
- struct ifaddr *if_addrlist; /* linked list of addresses per if */
- struct ifqueue -
- struct mbuf *ifq_head;
- struct mbuf *ifq_tail;
- int ifq_len;
- int ifq_maxlen;
- int ifq_drops;
- " if_snd; /* output queue */
- /* procedure handles */
- int (*if_init)(); /*init routine */
- int (*if_output)(); /* output routine (enqueue) */
- int (*if_start)(); /* initiate output routine */
- int (*if_done)(); /*output complete routine */
- int (*if_ioctl)(); /* ioctl routine */
- int (*if_reset)(); /* bus reset routine */
- int (*if_watchdog)(); /* timer routine */
- /* generic interface statistics */
- int if_ipackets; /* packetsreceived on interface */
-
-
- 84 Section 4.7 AmiTCP/IP System Manual
-
-
-
- int if_ierrors; /* input errors on interface */
- int if_opackets; /* packetssent on interface */
- int if_oerrors; /* output errorson interface */
- int if_collisions; /* collisions on csma interfaces */
- /* end statistics */
- struct ifnet *if_next;
- ";
-
-
- Network interface for SANA-II devices are handled in the module
- net/if_sana.c. This is the only module aware of SANA-II devices inside
- the AmiTCP/IP network process. It hides most SANA-II specific details
- from the rest of the code.
-
-
-
- Module Initialization
-
- ULONG sana_init(void)
-
- This initialization routine is called at startup time before any
- interfaces have been added to system. It creates the common message
- port used for all SANA-II network interfaces. It also attaches the
- loopback device into system. It returns the signal mask of the
- message port, if its creation was successful.
-
- void sana_deinit(void)
-
- This routine frees all resources allocated by the SANA-II interface
- module. It aborts all pending IO requests, frees them, closes
- network device drivers and frees the corresponding network
- interfaces. Finally it deletes the message port.
-
-
-
- 4.7.1 SANA-II Soft Network Interface
-
- A message passing system based on the normal Exec IO requests is used to
- transfer packets between the AmiTCP/IP and SANA-II devices. The IO can
- be either synchronous or asynchronous. The SANA-II interface module has
- a message port, which receives all fulfilled or aborted asynchronous IO
- messages. A dispatch method (currently a dispatch function pointer) have
- been added to all asynchronously sent IOrequests. Dispatching function
- handles the received message in an appropriate way.
- A messagemay contain received packet, some buffers allocated for the
- sent message or an event mask. Dispatcher functions feed the received
- data to the protocol input queues. If needed, the protocol input
- routines are run. Dispatchers also free the memory allocated for the
- sent packets, or relays events to the higher level protocols.
- Because the interface for the SANA-II device driver must handle many
- different protocols and network adapters, it has some private data hidden
- from the rest of the system. The struct sana_softc network interface is
- defined in file net/if_sana.h:
-
- /*
- * SANA-II Interface descriptor
- * NOTE: most of the code outside will believe this to be simply
- * a "struct ifnet". The other information is, on the other hand,
- * our own business.
-
-
- System Manual AmiTCP/IP Section 4.7 85
-
-
-
- */
- struct sana_softc -
- struct ifnet ss_if; /* network-visible interface */
- struct in_addr ss_ipaddr; /* copy of ip address */
- ULONG ss_hwtype; /* wiretype */
- UBYTE ss_hwaddr[MAXADDRSANA]; /* Generalhardware address */
- struct Device *ss_dev; /* pointer todevice */
- struct Unit *ss_unit; /* pointer to unit */
- VOID *ss_bufmgnt; /* magic cookie for buffer mngement */
- UWORD ss_reqno; /* # of requests to allocate */
- struct IOIPReq *ss_reqs; /* allocated requests*/
- struct MinList ss_freereq; /* free requests */
- #if INET
- struct -
- UWORD reqno; /* for listening ip packets */
- UWORD sent;
- ULONG type;
- " ss_ip;
- struct - /* for ARP */
- UWORD reqno;
- UWORD sent;
- ULONG type; /* ARP packet type */
- ULONG hrd; /*ARP header type */
- struct arptable *table; /* ARP/IP table */
- " ss_arp;
- #endif /* INET */
- UWORD ss_rawreqno; /* for raw packets */
- UWORD ss_rawsent;
- struct sana_softc *ss_next;
- char ss_name[IFNAMSIZ]; /* namelives here */
- ";
-
- There isan external interface to this structure via SIOCSSANATAGS and
- SIOCGSANATAGS ioctls.
-
-
- struct ifnet *iface_find(char *name)
-
- This function initializes a network interface for given interface.
- It is called on a non-existent interface from ifunit(). It tries to
- open the appropriate SANA-II device driver, and if successful it
- initializes a descriptor and calls if_attach() with it.
-
- Its argument is the device driver name concatenated with a slash and
- unit number. This name is used by AmiTCP/IP to open appropriate
- unit of the SANA-II driver.
-
- The initialization routine provides the specified SANA-II network
-
- device unit with the CopyToBuf() and CopyFromBuf() function tags8.
- Those tags are used to copy data to and from the internal buffers of
- the network device. The taglist given to the device driver is
- defined in file net/sana2copybuff.c.
-
- After successful open iface_find() initializes the appropriate
- members of the new sana_softc structure. It stores the device and
- unit pointers, magic cookie for buffer management, hardware type, MTU
- ________________________________
- 8For discussion for these functions, see [SANA-II 1992 add ]
-
-
- 86 Section 4.7 AmiTCP/IP System Manual
-
-
-
- and address length. It also searches for the hardware type specific
- taglist, and sets the rest of interface parameters according the
- taglist.
-
- Next the interface initialization routine attaches the new network
- interface into ifnet list with if_attach(). Then it initializes
- interface with if_init().
-
-
-
- Interface Routines
-
- BOOL sana_poll(void)
-
- The AmiTCP/IP processes received messages by calling this function.
- It effectively hides the actual implementation from the rest of the
- system. This routine is called when AmiTCP/IP receives the signal
- allocated by sana_init(), and it returns TRUE, if itshould be called
- again before Wait().
-
- sana_poll() retrieves messages from the message port, dispatches them
- and then runs the input queues.
-
- int sana_output(struct ifnet *ifp, struct mbuf *m0,
- struct sockaddr *dst, struct rtentry *rt)
-
- This function is used as the if_output() method. It tries to get a
- free IO request from the ss_freereq list. If no free request is
- available it drops the packet. It attaches the packet m0 to request,
- sets dispatching function to free_written_packet() and sends the
- request to the device driver.
-
- The raw packets to the SANA-II interface use the following variation
- of socket address. The addressing family of the raw packets must be
- AF_UNSPEC. Currently only the ARP uses the raw SANA-II packets.
-
-
- /*
- * A socket address for a generic SANA-II host
- */
- struct sockaddr_sana2 -
- u_char ss2_len;
- u_char ss2_family;
- u_long ss2_type;
- u_char ss2_host[MAXADDRSANA];
- ";
-
-
- void sana_ioctl(struct ifnet *ifp, int cmd, caddr_t data)
-
- This function is used as the if_ioctl() method. SANA-II devices and
- their respective network interfaces are configured via raw sockets by
- the IoctlSocket() requests. When the sana_ioctl() gets the
- SIOCSIFADDR request, it changes the IP address of the interface. The
- SIOCGIFFLAGS ioctl is used to set the parameter flags of the
-
- interface9.
-
- Special SANA-II configuration is done with SIOCSSANATAGS ioctl. It
- passes a tag list to the parse_sana_param_tags() function.
- ________________________________
- 9See file sys/ioctl.h for full listof all ioctls
-
-
- System Manual AmiTCP/IP Section 4.7 87
-
-
-
- void if_down(struct ifnet *ifp)
-
- This function pulls into if_ioctl() from net/if.h. if_down() marks
- the interface down and informs all affected network protocols about
- the matter. If the interface handles SANA-II device, it calls
- sana_down(), which handles the dirty work to put theinterface down.
-
- static void sana_run(struct sana_softc *ssc, int n, struct ifaddr *ifa)
-
- sana_run() configures the SANA-II interface and allocates the IO
- requests to use with the SANA-II device driver. Because the SANA-II
- device can be configured only once (see S2_CONFIGINTERFACE in
- [SANA-II 1992 add ]) the initialization routine does not configure it.
- Among other things the hardware address of the network adapter is set
- in configuration process. This function is called by the SIOGSIFADDR
- ioctl, which also sets the protocol address of the interface.
-
- static void sana_up(struct sana_softc *ssc)
-
- sana_up() marks interface up and enables the interface to listen the
- packets from the network. It sends read request with an appropriate
- packet type number and dispatch function to the device.
-
- static BOOL sana_down(struct sana_softc*ssc)
-
- sana_down() aborts all pending requests sent to a SANA-II device
- driver.
-
- static void sana_ip_read(struct sana_softc *ssc,
- struct IOIPReq *req) and
-
- static void sana_arp_read(struct sana_softc *ssc,
- struct IOIPReq *req)
-
- These dispatch functions are used to feed data from a network device
- to the protocol input queues. The network interface has not the
- input routines as members. Dispatching functions allocate mbufs for
- the next packet and send IO requests again to the network device.
-
-
-
- Statistics
-
- BSD Network interface contains a lot ofexcessive statistical data. Most
- of it is made redundant by the statistics gathered by the SANA-II driver.
- Because network statistics are not retrieved by looking at /dev/kmem,
- there is no need to gather BSD compatible statistics. A public ARexx
- port, named AMITCP, is set up for statistics retrieval and we can use
- appropriate SANA-II commands to get needed data when asked.
-
-
-
- 4.7.2 ARP
-
- The requirements for the ARP implementation for a SANA-II interface
- differ radically from the original implementation BSD. The original code
- was written exclusively for the Ethernet, which has a global addressing
- scheme and a fixed address length.
- The SANA-II ARP (in the module net/sana2arp.c) holds a separate address
- mapping cache for each interface. The number of entries in the cache may
-
-
- 88 Section 4.8 AmiTCP/IP System Manual
-
-
-
- be configured at the run time. The hardware address length varies from
- one interface to another. The mapping caches are hashtables with linked
- lists, so there is no limitations in thebucket size. ARP Table locking
- is done with a signal semaphore insteadof spln() functions.
- The ARP table is externally accessed only by IoctlSocket() calls. With
- the new SIOCGARPT ioctl the whole ARP cache may be read at once. There
- is no need to awkwardly read /dev/kmem.
-
-
-
- 4.8 Logging
-
-
- As everything is not predictable, programs like to inform the user about
- certain situations to help the user and/or maintainer to get programs
- work better. This is the motivation for log() and panic() functions.
- The fact that the file I/O routines can't be called from interrupts must
- be taken into account, since a program may want to inform the user even
- while executing at an interrupt level.
- Among thevery few functions of the AmigaOS which are callable from
- interrupts are GetMsg() and PutMsg(). These are used to implement the
- logging subsystem.
- When AmiTCP/IP has something to tell to the user, it first checks if
- there is any free messages available. There is only alimited number of
- these messages to use, since they are preallocated during
-
- initialization10. If there is no message available, a counter indicating
- that the message could not be deliveredis incremented. If a free
- message is available, the text given bycaller is printed into the buffer
- of the message. Then the message is sent to the private port of the
- NETTRACE task.
- The NETTRACE task is created early in the initialization of the
- AmiTCP/IP. This task waits for incomingmessages and when one arrives,
- it prints the message to the log windowand/or log file. Then message is
- freed by sending it back to AmiTCP/IP for reuse. If loss of log
- messages is detected, log() is called totell that to the user.
- The functions are defined as follows:
-
-
- int log(unsigned long level, const char*fmt, ...)
-
- This logs a message with format specified in exec.library/RawDoFmt(),
- similar to the printf(). It is preceded with ``<N>'' where N is a
- level as defined in file sys/syslog.h.
-
- void panic(const char *fmt, ...)
-
- When this function is called, we are in BIG trouble. If task, which
- called this, is not AmiTCP/IP, we just halt this task and send a
- message to AmiTCP/IP to halt immediately and free all resources.
- Format is as in exec.library/RawDoFmt().
-
- If AmiTCP/IP runs into a panic() it first patches all API functions
- to return an error code to the caller. Then, if the panic() was not
- in the context of the AmiTCP/IP it signals the AmiTCP/IP and halts.
- As the AmiTCP/IP receives the signal, it send a message to the log
- ________________________________
- 10This is because memory cannotbe allocated from interrupt code.
-
-
- System Manual AmiTCP/IP Section 4.9 89
-
-
-
- and signals all application programs waiting for network to take
- attention. As this is done, it opens an User Requester to inform the
- user. After the user responds, AmiTCP/IP waits for all library
- openers to close libraries and finally unloads itself from the
- memory.
-
- int printf(const char *fmt, ...)
-
- Like the normal C--library printf (with format of
- exec.library/RawDoFmt()) except that the printing is done using the
- logging mechanism.
-
- int sprintf(char *buf, const char *fmt,...)
-
- As in a normal C--library. Format is as in exec.library/RawDoFmt().
-
-
- All functions (except panic()) return number of printed (or logged)
- characters.
-
-
-
- Initialization Routines
-
- BOOL log_init(void)
-
- This function initializes NETTRACE subsystem by opening
- intuition.library for opening UserRequest in the case of panic().
- The the log messages are initialized to use by preallocating memory
- for them.
-
- Then NETTRACE is started and AmiTCP/IP waits for a signal from it.
- If NETTRACE success in it's initialization, then it sends a message
- back, which is then replied. If initialization fails, a variable is
- set to specific value and CTRL-F is sent to the AmiTCP/IP. If all
- this succeeds, the log messages are initialized and sent to
- logReplyPort which works as a queue for the free messages.
-
- void log_deinit(void)
-
- This works as reverse to initialization process. If NETTRACE is
- still running, a message is sent to it telling it to terminate. Then
- AmiTCP/IP waits until the message is replied. Then the memory
- reserved by the messages can be freed. Finally the intuition.library
- is closed.
-
-
-
- 4.9 ARexx Interface
-
-
- The ARexx port of the AmiTCP/IP is maintained by the NETTRACE task. The
- messages are parsed with parseline() (defined in kern/amiga_config.c).
-
-
-
- Initialization Routines
-
- ULONG rexx_init(void)
-
- This initialization routine is called at the startup time of the
- NETTRACE process. It opens the utility.library and the
- rexxsyslib.library to be used by the ARexx code and creates a public
-
-
- 90 Section 4.10 AmiTCP/IP System Manual
-
-
-
- ARexx message port. The signal mask of the ARexx port is returned
- upon a successful initialization.
-
-
- void rexx_deinit(void)
-
- Free all resources allocated by the ARexx interface module. First
- the ARexx port is removed from the system's list of message ports so
- that no-one is able find the port any more to send new messages.
- Then all pending messages are returned with error code set. Finally
- the ARexx port is deleted and libraries opened by rexx_init() are
- closed.
-
-
-
- Reply Routine
-
- BOOL rexx_poll(void)
-
- Checks if any ARexx messages has arrived and handles them one at a
- time. The parseline() function is used to parse and execute the
- given command. Returns TRUE if there might still be messages to
- handle, otherwise the return value is FALSE.
-
-
-
- 4.10 Application Interface Concepts
-
-
- 4.10.1 SocketBase -- an Extension of the Task Structure
-
- In Unix systems, where the network codeis integrated into the kernel, a
- process structure holds fields for per-process information of network
- related data. In AmiTCP/IP, where socket API is implemented as a shared
- library, each opener gets a newly created library base that holds data
- used by the AmiTCP/IP system. Each library base function makes sure
- that the caller is from the right Amigatask and refuses to operate if
- wrong task is attempting to use it (seesection 5.5 on page 100 for
- detailed information).
-
-
-
- 4.10.2 The System Call Semaphore and Task Priorities
-
- Currently, when program enters to some of socket library functions, it
- attempts to get semaphore to hold othercallers executing library code
- simultaneously. This is done so, since in Unix system,where this code
- originally runs, doesn't pre-empt process that is executing system call.
- In BSDSS, where ``Unix system calls'' run in user mode, system call
- emulation glue uses a mutex to prevent simultaneous use of that part of
- the server code. Although spl functions are used in NET/2 code to
- prevent simultaneous access of criticalsections, there may still be some
- sections that leave out protection if system call semaphore is removed.
- Unnecessary system call semaphore usageis going to be removed in later
- releases. Hopefully it, and the overhead it generates,becomes obsolete.
- The priority of the application process is raised to the same with the
- AmiTCP/IP, while the application executes AmiTCP/IP code. This is to
- prevent situations where a process witha low priority gets blocked for a
- long time while holding e.g. the system call semaphore, since otherwise
-
-
- System Manual AmiTCP/IP Section 4.11 91
-
-
-
- all networking programs would be blockedwith it. Thisapplies to all
- semaphores used internally by the AmiTCP/IP, not just the system call
- semaphore.
-
-
-
- Initialization Routines
-
- Making application interface visible andoperative contains a few steps:
- call to api_init() creates the master socket library base and initializes
- semaphores and lists API needs. Library base is not inExec library base
- list yet. Routine api_show() checks first if bsdsocket.library is
- already in Exec list and if not, calls Exec AddLibrary() to make it
- visible.
- AmiTCP/IPcan remove socket library from the Exec list at any time,
- i.e. make it not visible, by calling api _hide(). No new socket bases
- can be opened after this call. Socket bases opened before api _hide()
- operate normally. If AmiTCP/IP calls api_show() again, new libraries can
- be opened.
- api_setfunctions() takes all socket library bases out of operation. It
- sets all function vectors in every socket base to return an error. This
- function is called if AmiTCP/IP panic()ed and all libraries are expected
- to be closed.
- When application interface is to be removed from system, api_deinit()
- is called. It waits for all opened libraries to closeand then calls
- expunge function to deallocate the master socket base from the memory.
-
-
-
- 4.11 Configuration Variables
-
-
- The configuration variable definitions are stored into a structure named
- cfg_variable. It is defined in kern/amiga_netdb.h as follows:
-
-
- /* Variable types */
- /* Note: Query calls value, Set calls notify functions */
- enum var_type
- -
- VAR_FUNC = 1, /* value is function pointer */
- VAR_LONG, /* value is pointer to LONG */
- VAR_STRP, /* value is pointer to string */
- VAR_FLAG, /* LONG value is set once */
- VAR_INET, /* struct sockaddr_in */
- VAR_ENUM /* value is pointer to long, whose value is set
- according to a enumeration string in notify*/
- ";
-
-
- typedef LONG
- (*var_f)(struct CSource *args, UBYTE **errstrp, struct CSource *res);
- typedef int (*notify_f)(void *pt, LONG new);
-
-
- /* Configureable variable structure */
- struct cfg_variable -
- enum var_type type; /* type of value */
-
-
- 92 Section 4.12 AmiTCP/IP System Manual
-
-
-
- WORD flags; /* see below */
- const UBYTE *index; /* optional index keyword list */
- void *value; /* pointer to value... */
- notify_f notify; /* notification function */
- ";
-
-
- #define boolean_enum (notify_f)"NO=FALSE=OFF=0,YES=TRUE=ON=1"
-
-
- /* Variable flags */
- #define VF_TABLE (1<<0) /* with an index... */
- #define VF_READ (1<<1) /* readable */
- #define VF_WRITE (1<<2) /* writeable */
- #define VF_CONF (1<<3) /* writeable only during configuration */
- #define VF_RW (VF_WRITE_VF_READ)
- #define VF_RCONF (VF_CONF_VF_READ)
- #define VF_FREE (1<<8) /* free when replaced? */
-
-
- The configuration file (by default AmiTCP:db/AmiTCP.config) is read
- with the function readconfig(). This function also parses the command
- line arguments.
-
-
-
- 4.12 Network Database
-
-
- The network database is initialized by the init _netdb() function. This
- function allocates the NetDataBase structure and parses the file
- AmiTCP:db/netdb. The NetDataBase structure is definedas follows:
-
-
- struct NetDataBase -
- struct SignalSemaphore ndb_Lock;
- struct MinList ndb_Hosts;
- struct MinList ndb_Networks;
- struct MinList ndb_Services;
- struct MinList ndb_Protocols;
- struct MinList ndb_NameServers;
- struct MinList ndb_Domains;
- ";
-
-
- This structure contains a lock and lists for the different network
- database entries. The lock semaphore is obtained in the shared mode for
- reading, and in the exclusive mode for writing. See section 2.5.1 for
- the information about the different entries.
-
-
-
-
-
- Chapter 5
-
-
-
- Implementation Notes
-
-
-
- This chapter describes some points of the implementation of the
- AmiTCP/IP. The code that is not changedfrom the BSD net/2 -release is
- not reviewed. [Leffler et al 1989 ] describes the design and
- implementation of the BSD Unix, including the networking system.
- [Leffler et al 1991b ] is also very helpful.
- Most of the knowledge gathered during this project is gained by reading
- the source code itself. This chapter does not try to make that totally
- unnecessary.
-
-
-
- 5.1 Time outs
-
-
- The Unix timeout() function implements the time out needs of the Unix
- kernel. When kernel code calls timeout(), the functiongiven as argument
- will be called after the specified timeout has elapsed. In AmigaOS time
- outs are provided by the timer device. AmiTCP/IP sendstime out
- requests to the device and gets them back when the time specified has
- elapsed.
- The functions called by the time out service are:
-
-
- if_slowtimo()
-
- This is the time out function of the network interfaces and is
- defined in net/if.c.
-
-
- arptimer()
-
- Handles the time outs of ARP protocol (net/sana2arp.c).
-
-
- pfslowtimo()
-
- This is the main slow time out function for all protocols. It calls
- the pr_slowtimo() function of each configured protocol. The interval
- of this timer is 500 ms (kern/uipc_domain.c).
-
-
- pffasttimo()
-
- Is the corresponding function for fast (200 ms) time outs.
-
-
-
- 93
-
-
- 94 Section 5.1 AmiTCP/IP System Manual
-
-
-
- The request structure used by AmiTCP/IP has few fields in addition to
-
- the normal struct timerequest1. The structure is defined in
- kern/amiga_time.h as follows:
-
- struct timeoutRequest -
- struct timerequest timeout_request; /* timer.device sees only this */
- struct timeval timeout_timeval; /* timeout interval */
- TimerCallback_t timeout_function; /* timeout function to be called */
- ";
-
-
- In this implementation the time out functions themselves do not call
- any time out services, but the functionsare called by timer_poll(),
- which is called by main() when there might be a message to handle (e.g.
- when the timer signal is received). timer_poll() checks the reply port
- to see if there really is a message to handle. Afterthe time out
- function is serviced timer_poll() sends the request back to the timer
- device and returns.
- Time outservice is implemented by files kern/amiga_time.c and
- kern/amiga_time.h. The functions defined are:
-
-
- ULONG timer_init(void)
-
- Initializes the time out subsystem by allocating the IO requests and
- opening the timer device. Note that AmiTCP/IP uses functions that
- are new to version 36 of the timer device, so the code refuses to
- success with Kickstart 1.3 (or lower).
-
- Returns the signal mask to wait for if successful.
-
- void timer_deinit(void)
-
- Frees all resources used by time out subsystem.
-
- void timer_send(void)
-
- Sends time out requests allocated by timer_init() tothe timer
- device.
-
- struct timeoutRequest *createTimeoutRequest(TimerCallback_t fun,
- ULONG seconds, ULONG micros)
-
- Creates a new time out request. This can be called only after
- successful timer_init().
-
- void deleteTimeoutRequest(struct timeoutRequest *tr)
-
- Deletes requests created by createTimeoutRequest().
-
- BOOL timer_poll(VOID)
-
- Checks if there are any timer requests in the reply port and if there
- is handles them by calling the handleTimeoutRequest(). Then it sends
- the request back to the timer device.
-
- void handleTimeoutRequest(struct timeoutRequest *tr)
-
- Inline function which simply calls the function specified in the time
- out request.
- ________________________________
- 1See standard Amiga include file devices/timer.h
-
-
- System Manual AmiTCP/IP Section 5.2 95
-
-
-
- void sendTimeoutRequest(struct timeoutRequest *tr)
-
- Inline function which sends the request to the timer device.
-
-
- See the files kern/amiga_main.c and kern/amiga_time.c for example of
- the usage.
-
-
-
- 5.2 Memory Management
-
-
- 5.2.1 Mbufs
-
- Mbufs are ported just as they are. Memory is allocatedin small chunks
- for both mbufs and clusters. The size of the cluster and the number of
- mbufs to allocate in one chunk are configurable variables, see section
- 2.4 for summary of the configurable variables in general.
- Note thatsince data must be copied at the SANA-II interface there is
- no need to use trailer protocols (whosemain gain is avoidance of that
-
- copy) and so the mbuf clusters need notbegin at page boundaries2. This
- fact lead to the implementation of the clusters where the size of the
- cluster may be arbitrary (now user configurable) and the reference count
- of the cluster is stored in a little header before the actual data.
- One noteon allocating memory for the mbufs: Since the mbuf must be
- perfectly aligned (i.e. 128 byte mbuf must be 128--aligned), we need to
- allocate one extra mbuf to be able to align the mbufs in arbitrary memory
- chunk returned by Exec AllocMem().
- The 'canwait' argument of the mbuf functions is ignored by now, more
- memory will be allocated if limit of maximum memory usage is not hit.
- This is all right as long as the mbuf allocation functions are not called
- from interrupts. The only functions in the AmiTCP/IP which may get
- called from the interrupt code are the SANA-II callback functions
- m_copy_from_mbuf() and m_copy_to_mbuf()defined in file
- net/sana2copybuff.c.
- The function descriptions for the mbufs are on section 4.5. See files
- sys/mbuf.h and kern/uipc_mbuf.c for the actual implementation.
-
-
-
- 5.2.2 malloc() & free()
-
- Do not call the malloc() and free() functions directly! Since AmiTCP/IP
- is multi--threaded program these functions are not safe, since they use
- static data. File sys/malloc.h defines two inline functions to be used
- instead. They are defined as follows:
-
-
- static inline void * bsd_malloc(unsignedlong size, int type, int flags)
-
- This function calls malloc() to allocate memory of size size and type
- type. The types are defined in sys/malloc.h and are used for
- bookkeeping purposes. The flags may have either value M_WAITOK or
- M_NOWAIT. The flags are not used by this implementation, however, but
- are defined for portability.
- ________________________________
- 2Well, there is no virtual memory in Amiga either.
-
-
- 96 Section 5.3 AmiTCP/IP System Manual
-
-
-
- static inline void bsd_free(void *addr,int type)
-
- Frees memory allocated by bsd_malloc().
-
-
- The malloc() and free() are made safe by malloc_semaphore, which
- protects mallocs and frees from collisions. It is obtained before the
- actual calls to malloc() or free() and released after them.
- In addition to these functions sys/malloc.h defines macro versions for
- the most usual usages.
- Initialization for these functions is done by:
-
-
- BOOL malloc_init(void)
-
- Initializes the malloc_semaphore. This must be called early in the
- initialization process, since bsd_malloc() nor bsd_free() cannot be
- called before malloc_semaphore is initialized.
-
-
-
- 5.3 Concurrency Control
-
-
- 5.3.1 Processor Priority Levels
-
- In Unix systems the critical sections are mainly protected by raising the
- processor priority level (i.e. preventing interrupts upto a certain
- level). This crude way might hurt a real time operating system as the
- AmigaOS, so it can not be implemented assuch. Besides, the AmiTCP/IP
- runs as a normal user level process which has no needed privilege to
- alter the interrupt levels of the processor.
- The implementation in AmiTCP/IP is twofold; a semaphore is used in the
- debugging mode and task switch prevention is used in the production
- version. Using semaphore makes debugging easy as single stepping and
- tracing is possible while keeping the system alive. The semaphore adds
- certain overhead which is not acceptablein the production version, so
- the prevention of the task switches is used.
- When thepreprocessor symbol DEBUG is defined the spl_semaphore is
- used. When this semaphore is free the process is at level SPL0 (user
- level) and when the semaphore is allocated the process is at
- ``interrupt'' level (SPLSOFTCLOCK, SPLNET or SPLIMP), effectively
- disallowing anyone else to enter critical section. When the symbol DEBUG
- is not defined the functions and macrosare defined differently. They
- manipulate directly the Task Disable Nest Count (TDNextCnt field of the
- SysBase). This field is normally used by Exec functions Forbid() and
- Permit() which increment and decrement the value of the field,
- respectively. Since an assembler macro is provided byCommodore for the
-
- Forbid() function, the semantics of thefield cannot change in the future3.
- The semantics of the TDNestCnt is littleabused by the AmiTCP/IP, however.
- The value of the spl level in question is directly assigned as the value of
- the field. This is not visible outside of the AmiTCP/IP, since basically
- functions which use this field either directly or indirectly (via Forbid()/Perm*
- *it())
- need to return the value of the field asit was when the function was called.
- This is also the semantics of the usageof the spl functions.
- ________________________________
- 3If it would, then all the codeusing that official macro would break.
-
-
- System Manual AmiTCP/IP Section 5.3 97
-
-
-
- The spl_semaphore is initialized by the function BOOL spl_init(void)
- which is called among the very first functions in the initialization
- process.
- The function spl _n(int) (defined in sys/synch.h) is used to alter the
- priority levels. In the non-debugging mode there are two other
- functions, too: spl_const(), which isused with a constant (non-zero)
- argument, and spl_0() which is used to switch to the level 0. In
- addition, a macro has been defined for each separate level for
- portability. The macros are as follows:
-
-
- spl0() switches to the normal execution level.
-
-
- splsoftclock() is the level on which timer eventsare executed.
-
-
- splnet() is the level of the network interrupts in UNIX.
-
-
- splimp() is the highest of the priority levels used in the networking
- code. For example, mbuf functions are executed at this level.
-
-
- These macros return the previous level which may then be set back with
- splx(int)-macro, which sets the level tothe level given as argument.
-
-
-
- 5.3.2 Sleeping Facilities
-
-
- Sleeping facility is implemented by kern/kern _synch.c. Processes sleep
- on a channel, which is the key used to identify sleepers. Usually this
- is some address which is unique to the calling process. Socket base
- structure for the sleeping task is linked in the sleep queue before the
- actual sleep is started. This is how the waking task can find the
- sleeper to wake up when something happens on the channel the process is
- sleeping on.
- The sleepqueue is implemented as a hash table, where the channel value
-
- is mapped to an index of a sleep queue with the hash function4
- SLEEP_HASH() (defined in kern/kern_synch.c).
- The actual sleep is implemented by sending a time out request for the
- time out duration to the timer device. The sleep completes on the time
- out, a wakeup, a break signal or users specified signal.
- Note thatall critical resources (e.g. semaphores) must be freed
- before sleeping, since otherwise the whole networking code hangs.
- tsleep() does this for you.
- The functions which implement the sleep system are:
-
-
- BOOL sleep_init(void)
-
- This initializes the sleep_semaphore and the sleep queues. Thismust
- be called before any other functions of this module.
-
-
- int tsleep(struct SocketBase *p, caddr_tchan,
- char *wmesg, const struct timeval *time_out)
- ________________________________
- 4Actually a macro.
-
-
- 98 Section 5.3 AmiTCP/IP System Manual
-
-
-
- This function is the function usually called by the processes5 and
- implements the sleep by using the other functions of this module.
- The caller goes to sleep for at most the time specified in the struct
- timeval argument. chan is the channel to sleep on. wmesg is a
- string which is marked in the socket base (p) as the reason to sleep.
- Currently no-one ever reads it, though.
-
-
- void wakeup(caddr_t chan)
-
- Wakes up any sleepers on channel chan. Searches the sleep queue for
- entries with key chan and wakes them up by first clearing the key
- (p_wchan field of the socket base structure) and then signalling the
- process with the signal of the time out message. The usage of the
- sleep queues and the p_ fields in the socket base structures are
- protected with sleep_semaphore, which must be obtained before even
- reading the sleep queues.
-
- Note that since a task in AmigaOS may get signals anytime, the
- sleeper checks the p_wchan field on reception of thesignal and if it
- is nonzero it goes to sleep again.
-
-
- void tsleep_send_timeout(struct SocketBase *p,
- const struct timeval *time_out)
-
- First ensures that the message previously sent to the timer device is
- back. Then sends timer device a time out request for duration
- specified in time_out if it is not NULL. The requestsent is
- allocated when the library is opened.
-
-
- void tsleep_abort_timeout(struct SocketBase *p,
- const struct timeval *time_out)
-
- Aborts the time out sent by the tsleep_send_timeout(). This function
- must be used when the time out must be cancelled (when the sleeper is
- waken up).
-
- This function just sets the timer reply port (timerPort field of the
- socket base) to the mode in which reception of the message does not
- cause any action.
-
-
- void tsleep_enter(struct SocketBase *p,caddr_t chan, char *wmesg)
-
- Puts the caller on to a sleep queue.
-
-
- int tsleep_main(struct SocketBase *p, ULONG wakemask)
-
- Waits for either time out, wakeup, break or user defined action to
- happen. The sigIntrMask field of the socket base structure defines
- which signals will cause a break. Return value of EINTR is returned
- if any of the signals specified in that mask are received. In
- addition the signals are set back with SetSignal() for the user
- program to be able to detect them. The wakemask argument specifies a
- mask for signals which should cause a return from the sleep. In such
- case the return value ERESTART is returned.
- ________________________________
- 5Only WaitSelect() system calluses sleeping facilities without this
-
- function.
-
-
- System Manual AmiTCP/IP Section 5.4 99
-
-
-
- On exit the process is guaranteed not to be in the sleep queues any
- more, but the time out remains active if it is not the reason for
- return. Return value on wakeup is 0 and on time out EWOULDBLOCK is
- returned.
-
-
-
- 5.4 Socket Library Creation Procedure
-
-
- Since a new socket base is created eachtime a different task opens the
- AmiTCP/IP socket library, the procedureis a bit more complicated than
- on libraries where the same library baseis returned (See
- [RKM Libraries 1992 ]). There is, for example, two socket library bases
- in use. All code discussed here is located in api/amiga _api.c.
-
-
-
- 5.4.1 Master Library Base
-
- This is the library base that is made shown by api_show() (see section
- 4.10.2). It is placed in Exec's librarylist. This is of type struct
- Library and contains information that anoutsider can read by scanning
- through the Exec library list. Information available is version and
- revision numbers and count of tasks thathave (application) library base
- open.
- Master library base has only functions ELL_Open() and ELL_Expunge().
- When applications opens the socket library, the Exec calls ELL_Open().
- This function creates new application socket bases and increments the
- reference count of open application library bases. Ifthe calling task
- has a socket base open already, a new socket base is not created but the
- reference count of task's socket base isincremented and the base pointer
- is returned to the caller. This feature has many useful possibilities,
- for example in intermediate libraries which need to manipulate the
- sockets of the calling task.
- ELL_Expunge() does (not) do one task. When it is called, it checks if
- there is any libraries still open or ifAmiTCP/IP lets this function
- execute further (in fact, currently thissecond check is sufficient since
- only AmiTCP/IP can close the library andit doesn't do it until all
- bases has been closed. The next Remove() is there forfuture reference
- too). Then, the memory of the master library base is deallocated and
- NULL is returned (no AmigaDOS seglist tofree). The SIGBREAKF _CTRL_C
- signal that is sent with the global varianble SB _Expunged set to TRUE
- notifies api_deinit() function about the fact that now all libraries are
- closed.
-
-
-
- 5.4.2 Application Library Bases
-
- These are the library bases that are returned to the openers of the
- socket library. In this base the Open() function is obsolete since all
- OpenLibrary() calls go through the master socket base. Exec and
- AmiTCP/IP generated Expunge() calls go also through the master socket
- base.
- UL_Close() is the close function for all application library bases.
- First it decrements the reference countof this base and returns NULL if
-
-
- 100 Section 5.5 AmiTCP/IP System Manual
-
-
-
- there are still references left (again,NULL informs Exec that there is
- no AmigaDOS seglist needed to be removed).
- If thereare no more references to this library base, following steps
- are taken to remove it from the memory: All socket descriptors still
- open are closed. The base is removed from the AmiTCP/IP list of open
- application socket bases. The timer request is deallocated. Then the
- library base is removed from the memoryand open count of application
- socket bases is decremented in the master library base. Finally,
- ELL_Expunge() is called if the open count reached zero and the LIBF_DELEXP
- flag is set (by a previous ELL_Expunge() call).
-
-
-
- 5.5 The SocketBase Structure
-
-
- The SocketBase structure is defined in file api/amiga_api.h as follows:
-
-
- struct SocketBase -
- struct Library libNode;
- /* "Global" Errno */
- WORD errnoSize;
- /* -- now we are longword aligned -- */
- UBYTE * errnoPtr; /* this points to errno */
- LONG defErrno;
- /* Task pointer of owner task */
- struct Task * thisTask;
- /* task priority changes (WORDS so we keep structure longword aligned) */
- WORD myPri; /* task's priority just after libcall */
- WORD libCallPri; /* task's priority during library call */
- /* -- descriptor sets -- */
- WORD dTableSize;
- WORD nextDToSearch;
- struct socket ** dTable;
- /* AmiTCP signal masks */
- ULONG sigIntrMask;
- ULONG sigIOMask;
- ULONG sigUrgMask;
- /* -- these are used by tsleep()/wakeup() -- */
- char * p_wmesg;
- queue_chain_t p_sleep_link;
- caddr_t p_wchan; /* event processis awaiting */
- struct timerequest * tsleep_timer;
- struct MsgPort * timerPort;
- /* -- pointer to select buffer during Select() -- */
- struct newselbuf * p_sb;
- /* -- per process fields used by various'library' functions -- */
- /* buffer for inet_ntoa */
- char inet_ntoa[20]; /* xxx.xxx.xxx.xxx"0 */
- /* pointers for data buffers that MAY beused */
- struct DataBuffer selitems;
- struct DataBuffer hostents;
- struct DataBuffer netents;
- struct DataBuffer protoents;
- struct DataBuffer servents;
- ";
-
-
- System Manual AmiTCP/IP Section 5.6 101
-
-
-
- libNode is a normal library base structure and is used by the system.
- Since in this implementation each openergets a task specific library
- base, AmiTCP/IP links all ``user librarybases'' together using Node
- field of libNode.
- When socket library function encounters an error, it saves the value of
- the error to the memory location addressed by errnoPtr. errnoSize
- specifies the size of the variable pointed by the errnoPtr. By default
- errnoPtr points to the defErrno but canbe changed to point any memory
- location -- usually to the global errnovariable in the context of the
- user task.
- In entryof each bsdsocket.library function call, value of thisTask is
- compared to the task pointer of callingtask to make sure right task is
- calling the function. This variable is also used to find library base of
- some executing task.
- When taskis executing system calls in bsdsocket.library, its process
- priority is changed to the same as thatof the AmiTCP/IP task in order
- not to hold semaphores and block the whole network system. If some
- higher priority process becomes active and a lower priority task is
- holding some vital semaphore of the AmiTCP/IP then the precess cannot
- continue to run. The manipulation of the process priorities uses myPri
- and libCallPri fields of the socket base.
- dTableSize is the number of current maximum limit of socket
- descriptors. dTable is the descriptor table containingpointers to
- socket structures, i.e. sockets. nextDToSearch makes searching of free
-
- socket descriptor faster6.
- sigIntrMask is a task specific mask of the signals which should break
- the Wait() call in the tsleep_main(). Reception of such signals causes
- the system calls to return -1 and the error code pointed by errnoPtr to
- be set to EINTR. sigIOMask field specifies the signals to send when
- asynchronous notification is requested. Signals specified in sigUrgMask
- are sent when out of band data is received. These masks implement the
- functionality of the SIGIO and SIGURG signals of the Unix systems,
- respectively. All these masks can be set with the SetSocketSignals() API
- call. The default mask for the sigIntrMask specifies the signal for the
- ctrl-C, other two are zero by default.
- The nextgroup of variables are used by tsleep() and wakeup(). p_wmesg
- points to a string telling the reason why task is sleeping. p _sleep_link
- is used to chain library bases in the sleep queues. Waiting channel key
- is hold in variable p_wchan and data handling time outs in variables
- tsleep_timer and timerPort (more about this in section 5.3.2 on page 97).
- WaitSelect() inserts one selitem on each socket it wants event
- information of. p_sb points to a newselbuf that contains these items.
- Some APIfunctions in the original environment use static buffers to
- store their output. As a shared library cannot use static buffers (to be
- re-entrant), the buffers must be allocated dynamically. The SocketBase
- structure has space for the output buffer for the Inet_Ntoa() and
- pointers for other needed buffers. These buffers are allocated only when
- needed.
- ________________________________
- 6Semantics of allocating lowestfree socket descriptor is preserved.
-
-
- 102 Section 5.6 AmiTCP/IP System Manual
-
-
-
- 5.6 The Application Program Interface
-
-
-
- Most of API code is original NET/2 codetaken from BSDSS7. BSDSS mutexes
- are replaced by Amiga semaphores and struct proc references are changed
-
- to references to our socket library base8.
- Many functions used copyin() and copyout() to copy data around. Those
- functions copy data between system and user space (different virtual
- memory mappings) in original BSD Unix system. It is also possible that
- those functions will fail e.g. if user tries to reference illegal memory
- locations. In AmiTCP/IP system copyin() and copyout()functions are
- replaced with bcopy(), arguments are thesame but the bcopy() never
- fails. Therefore some obsolete checks are removed fromthe code.
-
-
-
- 5.6.1 HowAPI Functions Are Ported
-
-
- Most functions in our API are ported from BSD Unix system calls. BSD
- Unix system call interface calls the actual function with three
- arguments. First is user process structure pointer. Second contains the
- given arguments and is locally named asuap structure. Third argument is
- a pointer to the return value. The function returns error value or 0 if
- no error occurred.
- The socket() function is a good example of this:
-
-
-
- socket(p, uap, retval)
- struct proc *p;
- registerstruct args -
- int domain;
- int type;
- int protocol;
- " *uap;
- int *retval;
-
-
- The system function interface maps directly to Amiga shared library.
- Since every task has socket library baseof its own, Unix process pointer
-
- matches to library base pointer given inregister A69 . uap argumentsare
- passed in registers normally. Return value is returnedin the register
- D0 (as any standard C compiler does). So the *retval was changed to a
- local variable retval and removed, whennot needed. The returned value
- is -1 on error, in which case the errnois also set to indicate the error
- (see file sys/errno.h for list of errorcodes), or retval, or 0 if no
- other return value is needed.
- To emulate Unix system call interface, each function first obtains the
- syscall_semaphore (why,see section 4.10.2 on page 90) and while this
- task is holding the semaphore, no othertask can continue to execute the
- ________________________________
- 7BSDSS networking code is almost completely the same.
-
- 8See 5.5.
-
- 9All Amiga shared libraries expect them to be called relative to
-
- register A6
-
-
- System Manual AmiTCP/IP Section 5.7 103
-
-
-
- library code10. This means that every system call function needs to
- release syscall_semaphore before returning. To accomplish this, each
- return inside the function is changed togoto Return; and at label
-
- Return: is code that releases the syscall_semaphore11 .
- The default modifications were: changing file descriptor tables and
- pointers to socket tables and pointers,respectively, removing usage of
- struct fileops function pointers -- replacing them with direct socket
- functions, changing copyin() and copyout() functions to bcopy()s -- no
- more error checking here needed, and last, changing parameters on
- tsleep() calls.
-
-
-
- 5.6.2 APIFunctions Which Needed More Modifications
-
- IoctlSocket() (Former ioctl()): Non-socket stuff removed, and ioctl code
- from soo_ioctl() inserted.
-
- WaitSelect() (Former select()) usedto count remaining time out time if
- tsleep() returned accidentally too early. AmiTCP/IP uses the timer
- device for its time outs and the time out request is aborted only
- when it is needed again, so there is no need to send new time out
- requests (and to calculate their time out durations). tsleep() is
- broken apart into pieces so that the time out request is sent only
- once.
-
- CloseSocket() Decreases socket's referencecount and calls soclose() to
- kill the socket if it becomes zero.
-
- socket() and accept() Added initialization of so_refcnt. fdAlloc()
- doesn't bind fd to socket. It is done explicitly.
-
- Resolver functions used to allocate huge amounts of stack. Now memory is
- allocated dynamically from the head using bsd_malloc.
-
-
-
- 5.7 Changes in Functions Below API Level
-
-
- Functions that API functions call are mostly functions that use struct
- socket type arguments, possibly having some other arguments too. In most
- cases no modifications were needed. There was some modifications, like
- parameters for tsleep() call, which hadto be changed throughout the
- code.
-
-
-
- 5.7.1 Other Changes
-
- selscan() calls soo _select() directly, and uses socket pointer instead of
- file pointer.
-
- soo_select() also uses socket pointer instead of file pointer.
- ________________________________
- 10Not all functions require obtaining syscall_semaphore so those can continue
- to run.
- 11syscall_semaphore is also freed when library function does tsleep().
-
-
- 104 Section 5.8 AmiTCP/IP System Manual
-
-
-
- socreate() allows allsockets to be privileged. This means that user can
- obtain raw sockets and use normally privileged port numbers.
-
- sosend() uses uioread() instead of the original uiomove(). sblock() and
- sbwait() are called with library base pointer as the second argument.
-
- soreceive() uses uiowrite() instead of the original uiomove(). See above
- about the modification of call sblock() and sbwait().
-
- sorflush() calls sblock() with base pointer argument as NULL.
-
- sosetopt() and sogetopt() : type of so_linger and so_timeo fields in
- socket structure is changed from short int to struct timeval.
- Manipulation of these data is changed accordingly.
-
- sbwait() takes socket base pointer as second argument. It is then passed
- to tsleep() (see section 5.3.2 on page 97).
-
- sblock() and sb_lock(): sblock() is a macro that calls sb_lock(). Both
- take socket base pointer as second argument. sblock() forwards that
- pointer directly to sb_lock() which, again, passes it to the
- tsleep().
-
-
-
- 5.8 Agnet.device
-
-
- We used the agnet.device, an SANA-II test device, to test and develop the
- AmiTCP/IP network code. The usage and features of theagnet.device are
- described in the section 1.7.1, page 10.
- SANA-II is an standard network device driver interface for the Amiga
- (see [SANA-II 1992 add ]). It is an extension to the normal device
- interface, which is described in the [RKM Libs & Devs 1989 ]. Device
- drivers are accessed by their name fromthe system list. Drivers may be
- loaded dynamically from the disk, if they are not currently in the main
- memory. There may be several units sharing common driver code so each
- (network) device is specified by an unitnumber and the device driver
- name.
- We wrotethe agnet.device using the SLIP driver which Commodore has
- provided as the example code for SANA-IIdrivers. However, there was
- some problems with the supplied code. First, the SLIPdriver code
- obviously follows an obsolete SANA-II draft. There was some
- modifications in the final standard e.g. in the eventhandling and
- multicast addressing.
- The provided example code was also very fragile, it did not get
- compiled as such with the newer SAS C version 6. Codedepended on some
- features of the SAS C 5.10. For example, it always expected to find
- device base pointer in address registerA6.
-
-
-
- 5.8.1 IO Commands
-
- There is a detailed description of SANA-II device commands and functions
- in [SANA-II 1992 add ]. The following IO commands are implemented in
- agnet.device:
-
-
- System Manual AmiTCP/IP Section 5.8 105
-
-
-
- CMD_CLEAR
- This standard command should return IOERR_NOCMD when issued to
- SANA-II device.
-
- CMD_INVALID
- This standard command should return IOERR_NOCMD.
-
- CMD_READ
- Get the next packet available of the requested packet type. The data
- returned (via a call to the requester-provided CopyToBuffer()
- function) is the Data Link Layer packet data only. Raw packets are
- not supported.
-
- CMD_RESET
- This standard command should return IOERR_NOCMD when issued to
- SANA-II device.
-
- CMD_START
- This standard command should return IOERR_NOCMD when issued to
- SANA-II device.
-
- CMD_STOP
- This standard command should return IOERR_NOCMD when issued to
- SANA-II device.
-
- CMD_UPDATE
- This standard command should return IOERR_NOCMD when issued to
- SANA-II device.
-
- CMD_WRITE
- Send packet to the network. Raw packets are not supported. Sending
- packet with a broadcast hardware address is not supported.
-
- S2_BROADCAST
- Broadcast a packet to the network. Raw packets are not supported.
-
- S2_CONFIGINTERFACE
- Configure the interface. The address field will be set depending on
- the specified hardware type.
-
- S2_DEVICEQUERY
- Report the statistical information about the device.
-
- S2_GETGLOBALSTATS
- Report accumulated statistics as defined in struct Sana2Devicestats.
-
- S2_GETSTATIONADDRESS
- Report the ``hardware'' address for the unit. Before the
- configuration, the current hardware address has all bits set. The
- default hardware address is not stored anywhere.
-
- S2_GETTYPESTATS
- Report accumulated statistics of the tracked packets.
-
- S2_OFFLINE
- Remove interface from service. Flush all queued IO requests.
-
-
- 106 Section 5.8 AmiTCP/IP System Manual
-
-
-
- S2_ONEVENT
- Return when specified event(s) occur(s).
-
- S2_ONLINE
- Put the interface back in service. This command resets the unit
- statistics.
-
- S2_READORPHAN
- If there is no pending CMD_READ request with the type of the received
- packet, the packet is given to first pending S2_READORPHAN request.
- The data returned (via a call to the requester-provided CopyToBuffer
- function) is the Data Link Layer packet data only. Raw packets are
- not supported.
-
- S2_TRACKTYPE
- Start tracking of the specified packet type packets.
-
- S2_UNTRACKTYPE
- Stop tracking of the specified packet type packets.
-
-
-
- Uninplemeted IO Commands
-
- These SANA-II device commands are not supported.
-
- CMD_FLUSH
- This standard command returns IOERR_NOCMD when issued to the
- agnet.device.
-
- S2_ADDMULTICASTADDRESS
- This SANA-II command is not supported. It returns IOERR_NOCMD.
-
- S2_DELMULTICASTADDRESS
- This SANA-II command is not supported. It returns IOERR_NOCMD.
-
- S2_GETSPECIALSTATS
- This SANA-II command is not fully supported. It returns an empty
- Sana2SpecialStat structure.
-
- This command should report accumulated driver specific statistics.
- This includes ethernet ``retries''.
-
- S2_MULTICAST
- This SANA-II command is not supported. It returns IOERR_NOCMD.
-
-
-
- 5.8.2 Initialization Procedure
-
- agnet.device must be started as a DOS process by the Run command. The
- dynamic loading is not yet implemented. Its own startup module, init.c,
- opens needed libraries, initializes device base and calls the main()
- function. Main function opens timer.device and initializes the ARexx
- port; if initialization was successful,it adds the device base to the
- system list.
- In the main loop the device task waits for three different events:
- user or Expunge() generated break signal(SIGF _BREAK_F), ARexx messages or
- user IO request messages.
-
-
- System Manual AmiTCP/IP Section 5.8 107
-
-
-
- 5.8.3 TheDevice Interface Functions
-
- The device interface contains 6 standardlibrary calls in the device
- base. The device may be opened or closed, the IO requests may be
- initiated or aborted and the system mayreclaim storage allocated by the
- device driver.
- These library calls are not normally executed directly by the user code
- but instead higher level convenience functions in the Exec. The device
- base library calls are made in the context of the caller, so some
- synchronous IO commands may be executedlike library calls without
- message passing overhead (quick IO).
- The synopsis of the functions specifies the registers where the call
- parameters are passed (REG(rn)).
-
-
-
- Opening an Unit
-
- An IO device is opened by the Exec function call OpenDevice(). When Exec
- has found the named device driver in thesystem list it calls the special
- DevOpen() function from the device base. DevOpen() function has
- following synopsis:
-
- ULONG ASM DevOpen(REG(a1) struct IOSana2Req *ios2,
- REG(d0) ULONG unit, REG(d1) ULONG flags)
-
-
-
- The device open function tries to allocate and initialize various
- resources for the specified unit if the unit does not already exist.
- The initialization routine InitUnit() is called; if it returns an
- unit structure, a private buffermanagement structure is filled from
- the user provided tag list. The user supplied IO request is filled
- with appropriate values.
-
- The promiscuous or exclusive modes are not supported.
-
- struct AgnetDevUnit *InitUnit(ULONG);
-
- The initialization routine allocates an unit structure and then calls
- the configuration routine ReadConfig(). If the configuration file
- was read and interpreted without errors the lists and locks in the
- unit structure is initialized. The unit is then put online and unit
- structure is added to the device base.
-
- BOOL ReadConfig(struct AgnetDevUnit *adu)
-
- The configuration routine attempts to read in the configuration file
- for the given unit. It strips the comments out of the file and
- provides the file as a single line to the parsing routine
- ParseConfig(). If there is no configuration file, the parsing
- routine is called with an empty line.
-
-
-
- Closing an Unit
-
- The accessed unit is closed after use with the Exec CloseDevice()
- function. It runs the DevClose() function from the device base. The
- call has the following synopsis:
-
-
- 108 Section 5.8 AmiTCP/IP System Manual
-
-
-
- BPTR ASM DevClose(REG(a1) struct IOSana2Req *ios2)
-
- The device close function calls the unit close function. If the
- device has been asked to Expunge() itself, the close function sends
- an appropriate signal to the device task. The device task then
- performs the postponed expunge function.
-
- The DevOpen() and DevClose() calls are executed while Forbid()'den
- unless the code explicitly Wait()'s.
-
-
-
- Initiating an IO Request
-
-
- The DevBeginIO function from the devicebase is called to initiate an IO
- command. This call is made in the context of the requesting task (task
- calling Exec functions DoIO() or SendIO()). The DevBeginIO() call has
- the following synopsis:
-
-
- VOID ASM DevBeginIO(REG(a1) struct IOSana2Req *ios2)
-
- The IO request is sent to the device task for dispatching and
- execution. Currently all IO requests are executed in the context of
- the device task, i.e. no quick IO is supported.
-
-
-
- Aborting an IO Request
-
-
- Some IO requests may be aborted before they are completed by Exec
- function call AbortIO(). The aborting function has thefollowing
- synopsis:
-
-
- VOID ASM DevAbortIO(REG(a1) struct IOSana2Req *ios2)
-
- Currently only the CMD_READ, S2_READORPHAN, CMD_WRITE, S2_BROADCAST,
- and S2_ONEVENT IO commands may be aborted. Other IO commands are
- executed in an atomic way and can not be aborted reliably.
-
-
-
- Expunging the Device
-
-
- The system may reclaim the storage allocated by the device driver by
- calling the DevExpunge() function. Memory reclaiming is normally done in
- a low memory situation or after a user requested memory flush. The
- expunging function has the following synopsis:
-
-
- VOID ASM DevExpunge(VOID)
-
- The DevExpunge() may not Wait() because it may be called from the
- Exec function AllocMem() protected by Forbid()/Permit() pair.
-
- The DevExpunge() function call currently signals the device task,
- which performs the actual expunging by calling the DoExpunge(). Each
- unit structure is expunged by the function ExpungeUnit().
-
-
- System Manual AmiTCP/IP Section 5.8 109
-
-
-
- 5.8.4 Packet Delivery
-
- The packet sent to the pseudo network may be delayed or mutated randomly.
- A special structure (struct DelayRequest) stores the packet type and data
- during the ``transmit delay''. The delay is implemented by sending this
- structure as a the timer IO request to the timer device. The packet
- transmit functions are as follows:
-
-
- VOID WritePacket(struct AgnetDevUnit *adu, struct IOSana2Req *ios2)
-
- The function checks that the unit is on line and checks for the legal
- data length. Then the routine adds the given IO request (CMD_WRITE,
- S2_BROADCAST) into send queue. If there is a free delay request the
- SendPacket() is called immediately.
-
- VOID SendPacket(struct DelayRequest *delayed)
-
- The SendPacket() function takes an empty DelayRequest structure as
- its argument. First, it gets a send IO request from the send queue.
- The request is immediately returned if the packet is ``lost'' during
- transmit. This is repeated until a packet is found which is not to
- be lost.
-
- The packet data, type, length, transmission type and the address of
- the sender are then copied into the DelayRequest structure. If
- needed, bit errors are made into packet data.
-
- If there is specified delay for the unit, the request is sent to the
- timer device. After the delay the timer device returns request into
- the device port and it is dispatched by the ReceivePacket() function.
- If there is no delay, the ReceivePacket() is called immediately.
-
- VOID ReadPacket(struct AgnetDevUnit *adu, struct IOSana2Req *ios2)
-
- The function checks that unit is online, then adds the read request
- into an appropriate queue.
-
- VOID ReceivePacket(struct DelayRequest *delayed)
-
- The ReceivePacket() function calls the DoReceive() function on each
- unit the packet is destined. It then handles the DelayRequest
- structure back to the SendPacket() function.
-
- VOID DoReceive(struct AgnetDevUnit *adu,struct DelayRequest *delayed)
-
- The DoReceive() function tries to find a receive IO message waiting
- for this particular type packets. If none is found, the first
- S2_READORPHAN IO request is selected.
-
- The CopyBack() function sets the appropriate IO request return values
- and copies the packet data to the receive buffer.
-
-
-
- 5.8.5 Arexx Interface
-
- The ARexx interface is implemented by using the SimpleRexx package
- provided in Commodore Native Developer Update 2.0 kit. The Arexx
- commands executed by the agnet.device are described in section 1.7.1,
- page 12.
-
-
- 110 Section .0 AmiTCP/IP System Manual
-
-
-
- LONG ParseRexx(UBYTE *arg, UBYTE **errstr, UBYTE **result)
-
- The ARexx command string is copied into a buffer and passed to the
- parser function ParseRexx().
-
- The parser allocates a DOS struct RDArgs structure for the ARexx
- command. This structure holds the information for the DOS parsing
- functions. The first keyword in the string is read and tokenized by
- the DOS functions ReadItem() and FindArg().
-
- The rest of the line is parsed according this token. In the case of
- Query and Unit commands the unit number is read from the command line
- and the rest of the line is passed to the appropriate functions.
-
- LONG ParseConfig(struct AgnetDevUnit *adu, struct RDArgs *rdargs,
- STRPTR *errormessage)
- The command line stored into the RDArgs structure is parsed by the
- DOS function ReadArgs(). The parsed configuration information are
- then gathered, its legality is checked and it is stored into the unit
- structure.
-
- LONG ParseQuery(struct AgnetDevUnit *adu, struct RDArgs *rdargs,
- STRPTR *errstr, STRPTR *result)
- Like the ParseConfig(), ParseQuery() parses the command line by the
- ReadArgs(). It then fills the reply buffer by the requested
- configuration parameter values and then makes an ARexx string out of
- the buffer. This string is then returned to the ARexx process.
-